/**
 * 普通方法和Promise异步方法 事务处理，支持顺序执行，且方法之间返回结果的传递
 * @class
 *
 * ```js
 *
 * let p1 = ()=>new Promise((resolve, reject)=>{resolve(1)})
 * let p2 = ()=>new Promise((resolve, reject)=>{resolve(2)})
 * let asyncWalker = new AsyncWalker()
 * asyncWalker.use(p1)
 * asyncWalker.use(p2)
 * asyncWalker.execute()
 *
 * ```
 */


// import 'core-js/stable';
// import 'regenerator-runtime/runtime';
export default class AsyncWalker {
    constructor(){
        this.tasks = []
        this.res = []
        this.index = 0
    }

    /**
     * 将任务推入执行栈
     * @param {*} task 任务
     * @param {*} isBlockExp 报错是否中断任务
     * @param  {...any} args 方法参数
     * @returns 
     */
    use(task,isBlockExp,...args){
        let promiseTask
        if(task instanceof Promise){
            promiseTask = ()=>task
        }else if(typeof task === 'function'){
            promiseTask = task
        }else {
            promiseTask = ()=>{
                return new Promise((resolve)=>{
                    resolve(task)
                })
            }
        }
        this.tasks.push({
            task:promiseTask,
            block:isBlockExp,
            args:args
        })
        return this
    }

    execute(){
        let sequence = Promise.resolve()
        if(this.tasks.length > 0){
            sequence = Promise.resolve({
                prevResult:null,
                args:this.tasks[0].args
            })
            this.tasks.forEach((taskObj)=>{
                sequence = sequence.then(taskObj.task).then(data=>{
                    this.index ++
                    this.res.push(data)
                    return {
                        prevResult: data,
                        args:this.tasks[this.index]?.args
                    }
                }).catch(err=>{
                    let isBlock = this.tasks[this.index].block
                    if(isBlock){
                        throw new Error(err)
                    }
                    this.index ++
                    return {
                        prevResult: err,
                        args:this.tasks[this.index]?.args
                    }
                })
            })
        }
        return sequence
    }

    reset() {
        this.tasks = []
        this.res = []
        this.index = 0
    }
}


